package com.ruben.validator;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.regex.Pattern;

/**
 * @ClassName: PasswordValidator
 * @Description:
 * @Date: 2020/8/15 16:44
 * *
 * @author: achao<achao1441470436 @ gmail.com>
 * @version: 1.0
 * @since: JDK 1.8
 */
public class PasswordValidator implements ConstraintValidator<Password, String> {


    /**
     * Implements the validation logic.
     * The state of {@code value} must not be altered.
     * <p>
     * This method can be accessed concurrently, thread-safety must be ensured
     * by the implementation.
     *
     * @param value   object to validate
     * @param context context in which the constraint is evaluated
     * @return {@code false} if {@code value} does not pass the constraint
     */
    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        if (value.length() <= 6 || value.length() >= 20) {
            return false;
        }
        if (value.contains(" ")) {
            return false;
        }
        boolean hasUpperCase = false;
        boolean hasLowerCase = false;
        boolean hasNumber = false;
        boolean hasCharacter = false;
        String upperCaseRegexp = "^[A-Z]+$";
        String lowerCaseRegexp = "^[a-z]+$";
        String numberRegexp = "^[0-9]*$";
        Pattern upperCasePattern = Pattern.compile(upperCaseRegexp);
        Pattern lowerCasePattern = Pattern.compile(lowerCaseRegexp);
        Pattern numberPattern = Pattern.compile(numberRegexp);
        int countRepeat = 0;
        char[] chars = value.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            if (i != chars.length - 1 && chars[i] == chars[i + 1]) {
                countRepeat++;
            } else {
                countRepeat = 0;
            }
            if (countRepeat == 2) {
                return false;
            }
            String singleChar = String.valueOf(chars[i]);
            String chineseRegexp = "^[\\u4e00-\\u9fa5]*$";
            Pattern chinesePattern = Pattern.compile(chineseRegexp);
            if (chinesePattern.matcher(singleChar).matches()) {
                return false;
            }
            if (upperCasePattern.matcher(singleChar).matches()) {
                hasUpperCase = true;
            } else if (lowerCasePattern.matcher(singleChar).matches()) {
                hasLowerCase = true;
            } else if (numberPattern.matcher(singleChar).matches()) {
                hasNumber = true;
            } else {
                hasCharacter = true;
            }
        }
        int countMatches = 0;
        if (hasUpperCase) {
            countMatches++;
        }
        if (hasLowerCase) {
            countMatches++;
        }
        if (hasNumber) {
            countMatches++;
        }
        if (hasCharacter) {
            countMatches++;
        }
        return countMatches >= 3;
    }
}
